home *** CD-ROM | disk | FTP | other *** search
- // TPGPkey.cp - PGP Key Object
- //
- // Apple Macintosh Developer Technical Support
- // Written by: Vinnie Moscaritolo
- //
- // Copyright (work in progress) Apple Computer, Inc All rights reserved.
- //
- // You may incorporate this sample code into your applications without
- // restriction, though the sample code has been provided "AS IS" and the
- // responsibility for its operation is 100% yours. However, what you are
- // not permitted to do is to redistribute the source as "DSC Sample Code"
- // after having made changes. If you're going to re-distribute the source,
- // we require that you make it clear in the source that the code was
- // descended from Apple Sample Code, but that you've made changes.
- //
-
-
- #include <string.h>
- #include <TextUtils.h>
- #include <PLStringFuncs.h>
- #include "TPGPkey.h"
- #include "TPGPException.h"
-
- #include "pgpRandomPool.h"
- #include "pgpUserInterface.h"
- #include "pgpPublicKey.h"
-
-
-
- // ===========================================================================
- // Static member variables
- // ===========================================================================
-
- PGPContextRef TPGPkey::fgContext = kInvalidPGPContextRef; // PGP context
- PGPKeySetRef TPGPkey::fgPGPKeySetRef = kInvalidPGPKeySetRef; // this keyset
-
- // ---------------------------------------------------------------------------
- void TPGPkey::Initialize() // (static public)
- // ---------------------------------------------------------------------------
- // Create a new PGP context
- {
- if(! PGPContextRefIsValid(fgContext) )
- ThrowIfPGPErr( PGPNewContext( kPGPsdkAPIVersion, &fgContext));
-
- }
-
- // ---------------------------------------------------------------------------
- void TPGPkey::Initialize(PGPMemoryMgrRef memMgr) // (static public)
- // ---------------------------------------------------------------------------
- // Create a ustome PGP context
- {
-
- PGPNewContextStruct contextInfo;
-
- // Create a custom PGP context
- contextInfo.sizeofStruct = sizeof( PGPNewContextStruct );
- contextInfo.memoryMgr = memMgr;
-
- if(! PGPContextRefIsValid(fgContext) )
- ThrowIfPGPErr( PGPNewContextCustom( kPGPsdkAPIVersion, &contextInfo ,&fgContext));
-
- }
-
-
-
- // ---------------------------------------------------------------------------
- void TPGPkey::Finalize() // (static public)
- // ---------------------------------------------------------------------------
- // shutdown a new PGP context
- {
- if( PGPContextRefIsValid( fgContext)) PGPFreeContext(fgContext );
- fgContext = kInvalidPGPContextRef;
-
- }
-
- // ---------------------------------------------------------------------------
- void TPGPkey::OpenKeyDefaultRing() // (static public)
- // ---------------------------------------------------------------------------
- // Create a new PGP context
- {
- if( PGPContextRefIsValid(fgContext)
- && ( fgPGPKeySetRef == kInvalidPGPKeySetRef) )
- ThrowIfPGPErr( PGPOpenDefaultKeyRings(fgContext, 0, &fgPGPKeySetRef)) ;
- }
-
-
- // ---------------------------------------------------------------------------
- void TPGPkey::CloseKeyRing() // (static public)
- // ---------------------------------------------------------------------------
- // Create a new PGP context
- {
- if( PGPContextRefIsValid(fgContext) && PGPKeySetRefIsValid ( fgPGPKeySetRef ))
- PGPFreeKeySet (fgPGPKeySetRef );
-
- fgPGPKeySetRef = kInvalidPGPKeySetRef;
- }
-
-
-
- // ---------------------------------------------------------------------------
- void TPGPkey::Initialize(PGPKeyRef theKey)
- // ---------------------------------------------------------------------------
- //
- {
-
- if( PGPContextRefIsValid(fgContext)
- /* && PGPKeySetRefIsValid(fgPGPKeySetRef) */
- && PGPKeyRefIsValid(theKey))
- {
- PGPHashContextRef theHashRef = kInvalidPGPHashContextRef;
- PGPInt32 level;
- PGPTime theTime;
-
- ThrowIfPGPErr( PGPGetKeyNumber (theKey, kPGPKeyPropAlgID, (PGPInt32*) &fPublicKeyAlgorithm));
- ThrowIfPGPErr( PGPGetHashAlgUsed (theKey, &fHashAlgorithm) );
- ThrowIfPGPErr( PGPGetKeyBoolean (theKey, kPGPKeyPropIsExpired, &fExpired));
- ThrowIfPGPErr( PGPGetKeyBoolean (theKey, kPGPKeyPropIsRevoked, &fRevoked));
- ThrowIfPGPErr( PGPGetKeyBoolean (theKey, kPGPKeyPropIsDisabled, &fDisabled));
- ThrowIfPGPErr( PGPGetKeyBoolean (theKey, kPGPKeyPropIsAxiomatic,&fAxiomatic)) ;
- ThrowIfPGPErr( PGPGetKeyNumber(theKey, kPGPKeyPropBits, (PGPInt32*) &fKeySize));
- ThrowIfPGPErr( PGPGetKeyTime(theKey, kPGPKeyPropCreation, &theTime));
- fCreatedTime = PGPTimeToMacTime(theTime);
- ThrowIfPGPErr( PGPGetKeyTime(theKey, kPGPKeyPropExpiration, &theTime));
- fExpireTime = PGPTimeToMacTime(theTime);
-
- ThrowIfPGPErr (PGPNewHashContext( PGPGetContextMemoryMgr(fgContext), fHashAlgorithm, &theHashRef));
- ThrowIfPGPErr (PGPGetHashSize( theHashRef,&fHashSize));
- PGPFreeHashContext(theHashRef);
-
-
- ThrowIfPGPErr( PGPGetPrimaryUserIDValidity(theKey, &fValidity));
-
- ThrowIfPGPErr( PGPGetKeyNumber(theKey, kPGPKeyPropTrust, &level));
- switch(level)
- {
- default:
- case kPGPKeyTrust_Undefined:
- case kPGPKeyTrust_Unknown:
- case kPGPKeyTrust_Never:
- fTrustLevel = 0;
- break;
- case kPGPKeyTrust_Marginal:
- fTrustLevel = 1;
- break;
- case kPGPKeyTrust_Complete:
- fTrustLevel = 2;
- break;
- case kPGPKeyTrust_Ultimate:
- fTrustLevel = 3;
- break;
- }
- fKeyRef = theKey;
- fInitialized = true;
- }
- else
- {
- fKeyRef = kInvalidPGPKeyRef;
- fInitialized = false;
- }
- }
-
- // ---------------------------------------------------------------------------
- Boolean TPGPkey::CanSign()
- // ---------------------------------------------------------------------------
- // key can be used to sign
- {
- Boolean result = false;
-
- if( this->IsOperational() )
- ThrowIfPGPErr( PGPGetKeyBoolean (fKeyRef, kPGPKeyPropCanSign, &result));
-
- return result;
- }
-
- // ---------------------------------------------------------------------------
- Boolean TPGPkey::CanVerify()
- // ---------------------------------------------------------------------------
- // key can be used to sign
- {
- Boolean result = false;
-
- if( this->IsOperational() )
- ThrowIfPGPErr( PGPGetKeyBoolean (fKeyRef, kPGPKeyPropCanVerify, &result));
-
- return result;
- }
-
-
- // ---------------------------------------------------------------------------
- short TPGPkey::GetIconID()
- // ---------------------------------------------------------------------------
- // determine which icon to draw
- {
-
- short iconID = kAlertIcon_ID;
-
- if( fInitialized )
- {
- if(fPublicKeyAlgorithm == kPGPPublicKeyAlgorithm_RSA)
- {
- if( fRevoked) iconID = kIconRSA_Revoked_ID;
- else if(fExpired) iconID = kIconRSA_Expired_ID;
- else if(fDisabled) iconID = kIconRSA_Disabled_ID;
- else iconID = kIconRSA_ID;
- }
- else if(fPublicKeyAlgorithm == kPGPPublicKeyAlgorithm_DSA)
- {
- if(fRevoked) iconID = kIconDH_RevokedID;
- else if(fExpired) iconID = kIconDH_Expired_ID;
- else if(fDisabled) iconID = kIconDH_Disabled_ID;
- else iconID = kIconDH_ID;
- }
- }
-
- return iconID;
- }
-
- // ---------------------------------------------------------------------------
- void TPGPkey::GetPrimaryUserNamePString(StringPtr outbuf)
- // ---------------------------------------------------------------------------
- //
- {
- PGPSize bufLen;
- char buffer[256];
-
- ThrowIfPGPErr(PGPGetPrimaryUserIDNameBuffer(fKeyRef, sizeof( buffer) -1 , (char*) &buffer[1], &bufLen ));
-
- // truncate at email address
- buffer[0] = (strchr(&buffer[1], '<') - &buffer[1] - 1);
- PLstrcpy(outbuf,(StringPtr) buffer);
-
- }
-
-
- // ---------------------------------------------------------------------------
- void TPGPkey::GetFingerprintBinaryPString(void* outBuf)
- // ---------------------------------------------------------------------------
- //
- {
- PGPSize fpSize;
- unsigned char* p = (unsigned char*) outBuf;
-
- ThrowIfPGPErr( PGPGetKeyPropertyBuffer( fKeyRef, kPGPKeyPropFingerprint, MAX_PGPSize, NULL, &fpSize));
-
- ThrowIfPGPErr(PGPGetKeyPropertyBuffer( fKeyRef, kPGPKeyPropFingerprint, fpSize, &p[1], &fpSize));
-
- p[0] = (fpSize & 0xFF);
-
- }
-
-
- // ---------------------------------------------------------------------------
- void TPGPkey::GetFingerprintPString(StringPtr outBuf)
- // ---------------------------------------------------------------------------
- //
- {
- const char hexDigit[] = "0123456789ABCDEF";
- PGPSize bufLen;
- unsigned char buffer[255];
- int strIndex;
-
- ThrowIfPGPErr(PGPGetKeyPropertyBuffer( fKeyRef, kPGPKeyPropFingerprint, sizeof( buffer ), buffer, &bufLen));
-
- char *p = (char *) outBuf;
- *p++ = '\0';
-
- if(bufLen == 20)
- {
- for(strIndex = 0 ; strIndex < 20 ; strIndex++)
- {
- *p++ = hexDigit[buffer[strIndex]>>4];
- *p++ = hexDigit[buffer[strIndex]&0xF];
- if((strIndex == 1) || (strIndex == 3) || (strIndex == 5)
- || (strIndex == 7) || (strIndex == 11) ||
- (strIndex == 13)
- || (strIndex == 13) || (strIndex == 15) ||
- (strIndex == 17))
- *p++ = ' ';
- else if(strIndex == 9)
- {
- *p++ = ' ';
- *p++ = ' ';
- // *p++ = '\r';
- }
- }
- }
- else
- {
- for(strIndex = 0 ; strIndex < 16 ; strIndex++)
- {
- *p++ = hexDigit[buffer[strIndex]>>4];
- *p++ = hexDigit[buffer[strIndex]&0xF];
- if((strIndex == 1) || (strIndex == 3) || (strIndex == 5)
- || (strIndex == 9) || (strIndex == 11) || (strIndex == 13))
- *p++ = ' ';
- else if(strIndex == 7)
- {
- *p++ = ' ';
- *p++ = ' ';
- }
- }
- }
- outBuf[0] = (p - (char*)outBuf - 1) & 0xFF;
-
- }
-
-
- // ---------------------------------------------------------------------------
- void TPGPkey::GetPublicKeyAlgorithmPstring(StringPtr outBuf)
- // ---------------------------------------------------------------------------
- //
- {
- StringPtr algStr = "\pUnknown";
-
- if(outBuf)
- {
- if( fInitialized )
- switch(fPublicKeyAlgorithm)
- {
- case kPGPPublicKeyAlgorithm_Invalid: algStr = "\pInvalid"; break;
- case kPGPPublicKeyAlgorithm_RSA: algStr = "\pRSA"; break;
- case kPGPPublicKeyAlgorithm_RSAEncryptOnly: algStr = "\pRSA (Encrypt Only)"; break;
- case kPGPPublicKeyAlgorithm_RSASignOnly: algStr = "\pRSA (Sign Only)"; break;
- case kPGPPublicKeyAlgorithm_ElGamal: algStr = "\pDiffie-Hellman"; break;
- case kPGPPublicKeyAlgorithm_DSA: algStr = "\pDSS"; break;
- }
- PLstrcpy(outBuf,algStr);
- }
- }
-
-
-
-
-
- // ---------------------------------------------------------------------------
- void TPGPkey::Export(void** buf, PGPSize *bufSize )
- // ---------------------------------------------------------------------------
- //
- {
- if( this->IsOperational() )
- {
- PGPKeySetRef theKeyset;
- Str255 keyName;
-
- this->GetPrimaryUserNamePString(keyName);
- p2cstr(keyName);
-
- PGPNewSingletonKeySet( fKeyRef,&theKeyset );
- PGPExportKeySet( theKeyset,
- PGPOAllocatedOutputBuffer ( fgContext, buf, MAX_PGPUInt32, bufSize ),
- PGPOArmorOutput (fgContext, true),
- // PGPOVersionString (fgContext, "PGPUAM Version 1.0" ),
- PGPOCommentString (fgContext, (char*) keyName),
- PGPOLastOption( fgContext ));
-
- PGPFreeKeySet(theKeyset);
- }
-
-
- }
-
- // the behaviour of allowing disable keys to verify is questionable.
- // PGPTools allows a user to verify and decrypt with keys that have
- // been flagged by the user as disabled...BUT It could be argued that
- // this is the wroong thing to do in a server authentication environment
- // if disagree wit hthis feel free to disable the following define..
-
- #define DISABLED_KEYS_CANT_VERIFY 1
-
-
- // ---------------------------------------------------------------------------
- Boolean TPGPkey::Verify( void* inbuf, PGPSize inBufSize, void* sigbuf, PGPSize sigBufSize )
- // ---------------------------------------------------------------------------
- //
- {
- PGPError err = kPGPError_BadParams;
-
- if( this->IsOperational()
- #if DISABLED_KEYS_CANT_VERIFY
- && ! this->IsDisabled()
- #endif
- )
- {
- PGPHashContextRef theHashRef = kInvalidPGPHashContextRef;
- PGPPublicKeyContextRef thePublicKeyRef = kInvalidPGPPublicKeyContextRef;
-
- ThrowIfPGPErr( PGPNewHashContext( PGPGetContextMemoryMgr(fgContext), fHashAlgorithm, &theHashRef));
- ThrowIfPGPErr( PGPContinueHash( theHashRef,inbuf, inBufSize ));
-
- ThrowIfPGPErr( PGPNewPublicKeyContext( fKeyRef,
- kPGPPublicKeyMessageFormat_PGP,
- &thePublicKeyRef));
- err = PGPPublicKeyVerifySignature( thePublicKeyRef, theHashRef, sigbuf, sigBufSize) ;
-
- PGPFreePublicKeyContext(thePublicKeyRef);
- }
-
-
- return (err == kPGPError_NoErr) ;
-
- }
-
-
-
- // ---------------------------------------------------------------------------
- Boolean TPGPkey::Sign( void* inbuf, PGPSize inBufSize, void* sigbuf, PGPSize *sigBufSize, const char *passPhrase)
- // ---------------------------------------------------------------------------
- //
- {
- PGPError err = kPGPError_BadParams;
-
- if( this->IsOperational() )
- {
-
- PGPHashContextRef theHashRef = kInvalidPGPHashContextRef;
- PGPPrivateKeyContextRef thePrivateKeyRef = kInvalidPGPPrivateKeyContextRef;
-
- ThrowIfPGPErr( PGPNewHashContext( PGPGetContextMemoryMgr(fgContext), fHashAlgorithm, &theHashRef));
- ThrowIfPGPErr( PGPContinueHash( theHashRef,inbuf, inBufSize ));
-
- err = PGPNewPrivateKeyContext( fKeyRef, kPGPPublicKeyMessageFormat_PGP, &thePrivateKeyRef,
- PGPOPassphrase( fgContext, passPhrase),
- PGPOLastOption( fgContext ));
- if(err == kPGPError_NoErr)
- {
- ThrowIfPGPErr( PGPPrivateKeySign( thePrivateKeyRef, theHashRef, sigbuf, sigBufSize ));
- PGPFreePrivateKeyContext(thePrivateKeyRef);
- }
- }
-
- return (err == kPGPError_NoErr) ;
- }
-